package ru.spbu.math.android.cbrf.dataprovider;

import android.content.Context;
import ru.spbu.math.android.cbrf.model.Rate;
import ru.spbu.math.android.cbrf.model.RateType;
import ru.spbu.math.android.cbrf.model.StockItem;

import java.util.Date;
import java.util.List;

public class DataProvider {

	private static DataProvider self;
	private RateDatabase database;
	private Validator validator;

	public static DataProvider getInstance(Context context) {
		if (self == null) {
			self = new DataProvider(context);
		}
		return self;
	}

	public static enum RateTypeGroups {
		Metal, 
		Currency, 
		Oil
	}
	
	/**
	 * @param source
	 * @param target
	 * @return latest available Rate with fit source and target StockItems
	 * @throws IllegalStockItemsCombinationException
	 * 
	 * @throws NullResultException
	 */
	public Rate getLatestRate(StockItem source, StockItem target)
			throws IllegalStockItemsCombinationException {

		if (validator.validate(source, target)) {

			IProvider provider = validator.getProvider(source, target);

			if (provider.isUpdatableNow()) {

				Rate rate = provider.getLatestRate(source, target);
				database.addRate(rate);
				return rate;

			} else {

				return database.getLatestRate(source, target);
			}

		} else {
			throw new IllegalStockItemsCombinationException();
		}
	}

	/**
	 * @param source
	 * @param target
	 * @param since
	 * @param until
	 * @return Rates dynamic as array of Rates
	 * @throws IllegalStockItemsCombinationException
	 */
	public Rate[] getDynamicRates(StockItem source, StockItem target,
			Date since, Date until) throws IllegalStockItemsCombinationException{

		if (validator.validate(source, target)) {

			IProvider provider = validator.getProvider(source, target);

			if (provider.isUpdatableNow()) {

				Rate[] rate = provider.getDynamicRates(source, target, since, until);
				if (rate == null) {
					return database.getDynamicRates(source, target, since, until);
				} else {
					database.addRates(rate);
				}
				return rate;
			} else {

				return database.getDynamicRates(source, target, since, until);
			}
		} else {
			throw new IllegalStockItemsCombinationException(); 
		}
	}

//	/**
//	 * @return Rate with concrete values of date and name
//	 * @throws NullResultException
//	 */
//	public Date getLatestUpdateTime() {
//		return database.getLatestUpdateTime();
//	}

//	/**
//	 * @param source
//	 * @param target
//	 * @return latest Rate.date value for Rates with fit source and target
//	 * @throws NullResultException
//	 */
//	public Date getLatestUpdateTime(StockItem source, StockItem target) {
//		return database.getLatestUpdateTime(source, target);
//	}

	/**
	 * @param context
	 */
	private DataProvider(Context context) {
		validator = new Validator();
		database = new RateDatabase(context);
	}

	/*
	 * Select the RateTypes which belong to the RateTypeGroup.
	 */

	public List<RateType> getRateTypesByGroup(RateTypeGroups group) {

		return validator.getRateTypes(group);
	}

	/**
	 * @param source
	 * @param target
	 * @return difference between new value and old value
	 * @throws IllegalStockItemsCombinationException
	 */
	public double getIncrease(StockItem source, StockItem target) throws IllegalStockItemsCombinationException {

			Rate last = getLatestRate(source, target);
			Rate previous = database.getPreviousRate(source, target);
			if (previous == null) {
				return 0;
			}

			double res = last.getValue() - previous.getValue();
			res = Math.round(res * 100000) / 100000.0;
			return res;
	}
}
